import os
import subprocess
import uuid

from django.conf import settings
from httprunner.cli import main_run
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response

from sqtp.models.task import Plan, Report
from sqtp.serializers import CaseSerializer
from sqtp.serializers.task import PlanSerializer, ReportSerializer
from sqtp.utils.utils import Utils


class PlanViewSet(viewsets.ModelViewSet):
    queryset = Plan.objects.all()
    serializer_class = PlanSerializer

    def perform_create(self, serializer):
        serializer.save(create_by=self.request.user)

    def perform_update(self, serializer):
        serializer.save(update_by=self.request.user)

    @action(detail=True, methods=['GET'], url_path='run', url_name='run_plan')
    def run_plan(self, request, pk):
        try:
            plan = Plan.objects.get(pk=pk)
            plan.status = 1
            plan.save()
            Utils.setup_case_dir(settings.TEST_FILES_DIR)
        except Plan.DoesNotExist:
            return ValidationError("Plan does not exist.")
        case_list = []  # 用例路径
        for case in plan.cases.all():  # 生成测试文件
            case_serializer = CaseSerializer(instance=case)
            path = case_serializer.to_json_file()
            case_list.append(path)

        allure_path = f"{os.path.join(settings.BASE_DIR, 'allure')}/{uuid.uuid4()}"
        if case_list:
            exit_code = main_run([*case_list, f'--alluredir={allure_path}'])
        else:
            return Response(status=304, data={'error': 'no cases', 'recode': 304})

        # 启动一个新的进程来执行指定命令，不会像 os.system 那样阻塞主进程，可以异步执行
        subprocess.Popen(['allure', 'generate', allure_path, '-o', f'dist/{allure_path}'])

        plan.status = 3
        plan.exec_counts += 1
        plan.save()

        detail = Utils.collect_log('log')
        Report.objects.create(plan=plan, path=f'{allure_path}/index.html', trigger=request.user,detail=detail)

        if exit_code != 0:
            return Response(
                status=500,
                data={
                    'status': 500,
                    'error': '计划执行失败',
                    'exit_code': exit_code,
                }
            )
        return Response(
            status=200,
            data={
                'status': 200,
                'msg': '报告生成成功',
                'retcode': 200
            }
        )


class ReportViewSet(viewsets.ModelViewSet):
    queryset = Report.objects.all()
    serializer_class = ReportSerializer

    def create(self, request, *args, **kwargs):
        return Response(
            status=404,
            data={
                'error': "no method",
                'retcode': 404,
            }
        )

    def update(self, request, *args, **kwargs):
        return Response(
            status=404,
            data={
                'error': "no method",
                'retcode': 404,
            }
        )
